package lambdasinaction.chap8.my;

import java.util.function.Function;
import java.util.function.UnaryOperator;

/**
 * 责任链模式 是一种创建处理对象序列（比如操作序列）的通用方案。 一个处理对象可能需要在完成一些工作之后，将结果传递给另一个对象，这个对象接着做一些工作， 再转交给下一个处理对象，以此类推。
 * 通常，这种模式是通过定义一个代表处理对象的抽象类来实现的，在抽闲类中会定义一个字段来记录后续对象。 一旦对象完成它的工作，处理对象就会将它的工作转交给它的后继。
 *
 * @author Fish
 * @since 0.0.1 2018/8/8 18:27
 */
public class MyChainOfResponsibilityMain {

  static private abstract class ProcessingObject<T> {

    protected ProcessingObject<T> successor;

    public static void main(String[] args) {
      /**
       * 现在你就可以将这两个处理对象结合起来，构造一个操作序列！
       */
      ProcessingObject<String> p1 = new HeaderTextProcessing();
      ProcessingObject<String> p2 = new SpellCheckerProcessing();
      p1.setSuccessor(p2);

      String result = p1.handle("Aren't labdas really sexy? !!");
      System.out.println(result);

      /**
       * 使用 Lambda 表达式
       * 稍等！这个模式看起来像是在链接（也即是构造）函数。
       * 第3章中我们探讨过如何构造 Lambda 表达式。
       * 你可以将处理对象作为函数的一个实例，或者更确切地说作为 UnaryOperator<String> 的一个实例。
       * 为了链接这些函数，你需要使用 andThen 方法对其进行构造。
       */
      // 第一个处理对象
      UnaryOperator<String> headerProcessing = (String text) -> "Form Raoul, Mario and Alan:"
          + text;

      // 第二个处理对象
      UnaryOperator<String> spellCheckerProcessing = (String text) -> text.replaceAll("labda", "lambdas");

      // 将两个方法结合起来，结果就是一个操作链
      Function<String, String> pipeline = headerProcessing.andThen(spellCheckerProcessing);
      String result2 = pipeline.apply("Aren't labdas really sexy?!!");
      System.out.println(result2);
    }

    public void setSuccessor(ProcessingObject<T> successor) {
      this.successor = successor;
    }

    /**
     * handle 方法提供了如何进行工作处理的框架。 不同的处理对象可以通过继承 ProcessingObject 类 提供 handleWork 方法来进行创建
     */
    public T handle(T input) {
      T r = handleWork(input);
      if (successor != null) {
        return successor.handle(r);
      }
      return r;
    }

    abstract protected T handleWork(T input);

    /**
     * 下面让我们来看看如何使用该设计模式。 你可以创建两个处理对象，它们的功能是进行一些文本工作
     */
    private static class HeaderTextProcessing extends ProcessingObject<String> {

      @Override
      protected String handleWork(String text) {
        return "From Raoul, Mario and Alan: " + text;
      }
    }

    private static class SpellCheckerProcessing extends ProcessingObject<String> {

      @Override
      protected String handleWork(String text) {
        return text.replaceAll("labda", "lambda"); // 糟糕，我们漏掉了 Lambda 中的 m字符
      }
    }
  }

}
